

#include <dpl/log.h>
#include <dpl/os.h>
#include <dpl/config.h>

D_LOG_DOMAIN(mutex_test,"this is a case, how to use");



/* Test witn non-recursive mutex. */
static int simple_mutex_test(dpl_pool_t *pool)
{
    dpl_status_t rc;
    dpl_mutex_t *mutex;

    dpl_i("", "...testing simple mutex");
    
    /* Create mutex. */
    dpl_v("", "....create mutex");
    rc = dpl_mutex_create( pool, "", DPL_MUTEX_SIMPLE, &mutex);
    if (rc != DPL_SUCCESS) {
	dpl_e("...error: dpl_mutex_create", rc);
	return -10;
    }

    /* Normal lock/unlock cycle. */
    dpl_v("", "....lock mutex");
    rc = dpl_mutex_lock(mutex);
    if (rc != DPL_SUCCESS) {
	dpl_e("...error: dpl_mutex_lock", rc);
	return -20;
    }
    dpl_v("", "....unlock mutex");
    rc = dpl_mutex_unlock(mutex);
    if (rc != DPL_SUCCESS) {
	dpl_e("...error: dpl_mutex_unlock", rc);
	return -30;
    }
    
    /* Lock again. */
    dpl_v("", "....lock mutex");
    rc = dpl_mutex_lock(mutex);
    if (rc != DPL_SUCCESS) return -40;

    /* Try-lock should fail. It should not deadlocked. */
    dpl_v("", "....trylock mutex");
    rc = dpl_mutex_trylock(mutex);
    if (rc == DPL_SUCCESS)
	dpl_i("", "...info: looks like simple mutex is recursive");

    /* Unlock and done. */
    dpl_v("", "....unlock mutex");
    rc = dpl_mutex_unlock(mutex);
    if (rc != DPL_SUCCESS) return -50;

    dpl_v("", "....destroy mutex");
    rc = dpl_mutex_destroy(mutex);
    if (rc != DPL_SUCCESS) return -60;

    dpl_v("", "....done");
    return DPL_SUCCESS;
}


/* Test with recursive mutex. */
static int recursive_mutex_test(dpl_pool_t *pool)
{
    dpl_status_t rc;
    dpl_mutex_t *mutex;

    dpl_i( "...testing recursive mutex");

    /* Create mutex. */
    dpl_v("....create mutex");
    rc = dpl_mutex_create( pool, "", DPL_MUTEX_RECURSE, &mutex);
    if (rc != DPL_SUCCESS) {
	dpl_e("...error: dpl_mutex_create %d", rc);
	return -10;
    }

    /* Normal lock/unlock cycle. */
    dpl_v( "....lock mutex");
    rc = dpl_mutex_lock(mutex);
    if (rc != DPL_SUCCESS) {
	dpl_e("...error: dpl_mutex_lock %d", rc);
	return -20;
    }
    dpl_v("", "....unlock mutex");
    rc = dpl_mutex_unlock(mutex);
    if (rc != DPL_SUCCESS) {
	dpl_v("...error: dpl_mutex_unlock", rc);
	return -30;
    }
    
    /* Lock again. */
    dpl_v( "....lock mutex");
    rc = dpl_mutex_lock(mutex);
    if (rc != DPL_SUCCESS) return -40;

    /* Try-lock should NOT fail. . */
    dpl_v("....trylock mutex");
    rc = dpl_mutex_trylock(mutex);
    if (rc != DPL_SUCCESS) {
	dpl_e("...error: recursive mutex is not recursive!", rc);
	return -40;
    }

    /* Locking again should not fail. */
    dpl_v("", "....lock mutex");
    rc = dpl_mutex_lock(mutex);
    if (rc != DPL_SUCCESS) {
	dpl_e("...error: recursive mutex is not recursive!", rc);
	return -45;
    }

    /* Unlock several times and done. */
    dpl_v("", "....unlock mutex 3x");
    rc = dpl_mutex_unlock(mutex);
    if (rc != DPL_SUCCESS) return -50;
    rc = dpl_mutex_unlock(mutex);
    if (rc != DPL_SUCCESS) return -51;
    rc = dpl_mutex_unlock(mutex);
    if (rc != DPL_SUCCESS) return -52;

    dpl_v("", "....destroy mutex");
    rc = dpl_mutex_destroy(mutex);
    if (rc != DPL_SUCCESS) return -60;

    dpl_v("", "....done");
    return DPL_SUCCESS;
}

#ifdef DPL_HAS_SEMAPHORE
static int semaphore_test(dpl_pool_t *pool)
{
    dpl_sem_t *sem;
    dpl_status_t status;

    dpl_i("", "...testing semaphore");

    status = dpl_sem_create(pool, NULL, 0, 1, &sem);
    if (status != DPL_SUCCESS) {
	dpl_e("...error: dpl_sem_create()", status);
	return -151;
    }

    status = dpl_sem_post(sem);
    if (status != DPL_SUCCESS) {
	dpl_e("...error: dpl_sem_post()", status);
	dpl_sem_destroy(sem);
	return -153;
    }

    status = dpl_sem_trywait(sem);
    if (status != DPL_SUCCESS) {
	dpl_e("...error: dpl_sem_trywait()", status);
	dpl_sem_destroy(sem);
	return -156;
    }

    status = dpl_sem_post(sem);
    if (status != DPL_SUCCESS) {
	dpl_e("...error: dpl_sem_post()", status);
	dpl_sem_destroy(sem);
	return -159;
    }

    status = dpl_sem_wait(sem);
    if (status != DPL_SUCCESS) {
	dpl_e("...error: dpl_sem_wait()", status);
	dpl_sem_destroy(sem);
	return -161;
    }

    status = dpl_sem_destroy(sem);
    if (status != DPL_SUCCESS) {
	dpl_e("...error: dpl_sem_destroy()", status);
	return -163;
    }

    return 0;
}
#endif	/* DPL_HAS_SEMAPHORE */


int test_mutex(void)
{

	dpl_i("Enter test!");
    dpl_pool_t *pool;
    int rc;

    //pool = dpl_pool_create(mem, "", 4000, 4000, NULL);

    rc = simple_mutex_test(pool);
    if (rc != 0)
	return rc;

    rc = recursive_mutex_test(pool);
    if (rc != 0)
	return rc;

#ifdef DPL_HAS_SEMAPHORE
    rc = semaphore_test(pool);
    if (rc != 0)
	return rc;
#endif

    //dpl_pool_release(pool);

    return 0;
}

